سیستم تحلیل و پیش‌بینی کیفی
پروژه داده‌کاوی

1 درباره دیتاست و متغیرها

1.1 معرفی دیتاست Wine Quality

مجموعه داده کیفیت شراب که توسط Cortez و همکارانش در سال ۲۰۰۹ گردآوری شده، شامل اطلاعات شراب‌های قرمز و سفید منطقه Vinho Verde در شمال پرتغال است. این دیتاست در واقع تلاشی برای پل زدن میان دو دنیای متفاوت است: دنیای دقیق و قابل اندازه‌گیری شیمی، و دنیای ذهنی و حسی ارزیابی انسانی.

شراب‌ها بر اساس ۱۱ ویژگی فیزیکوشیمیایی توصیف شده‌اند که همگی به صورت کمی قابل سنجش هستند - از میزان اسیدهای مختلف گرفته تا چگالی و درصد الکل. اما خروجی مورد نظر، یعنی متغیر کیفیت (Quality)، حاصل قضاوت حسی سه کارشناس است که نمره‌ای بین ۰ تا ۱۰ به هر نمونه داده‌اند.

البته نکته جالب این است که در عمل، هیچ شرابی نمره صفر یا ده نگرفته. تمام امتیازها در بازه ۳ تا ۸ قرار دارند که این موضوع خود بیانگر محدودیت طبیعی داده‌هاست. برای تسهیل تحلیل، معمولاً این امتیازها به دو دسته کیفیت بالا (HIGH) و کیفیت پایین (LOW) تقسیم می‌شوند تا مسئله از حالت رگرسیون به طبقه‌بندی دودویی تبدیل شود.

1.2 جدول توضیحات متغیرها

در جدول زیر، توضیح مختصری از هر یک از متغیرهای موجود در دیتاست آورده شده است:

نام انگلیسی ترجمه فارسی توضیحات فنی
Fixed Acidity اسیدیته ثابت اسیدهای غیرفراری که در شراب به صورت طبیعی وجود دارند (مانند اسید تارتاریک)
Volatile Acidity اسیدیته فرار اسیدهایی که تبخیر می‌شوند؛ میزان بالا نشانه فساد احتمالی است
Citric Acid اسید سیتریک مسئول طراوت و تیزی طعم؛ در مقادیر کم به عنوان نگهدارنده عمل می‌کند
Residual Sugar قند باقیمانده قندی که پس از تخمیر در شراب باقی می‌ماند
Chlorides کلریدها میزان نمک موجود در شراب
Free Sulfur Dioxide دی‌اکسید گوگرد آزاد فرم فعال SO₂ که از اکسیداسیون و رشد میکروب‌ها جلوگیری می‌کند
Total Sulfur Dioxide دی‌اکسید گوگرد کل مجموع اشکال آزاد و متصل SO₂
Density چگالی جرم حجمی مایع که به میزان الکل و قند بستگی دارد
pH پی‌اچ سطح اسیدی یا بازی بودن (مقیاس ۰ تا ۱۴)
Sulphates سولفات‌ها افزودنی‌هایی برای نگهداری و جلوگیری از اکسیداسیون
Alcohol الکل درصد الکل موجود در شراب
Quality کیفیت امتیاز حسی (متغیر هدف): HIGH یا LOW
Id شناسه شماره ردیف (بدون ارزش تحلیلی)

2 بارگذاری داده‌ها و کتابخانه‌های مورد نیاز

2.1 بارگذاری کتابخانه‌های R

اولین گام در هر پروژه تحلیل داده، بارگذاری کتابخانه‌های ضروری است. در این پژوهش از مجموعه‌ای از ابزارهای قدرتمند R برای پیش‌پردازش، تحلیل اکتشافی و مدل‌سازی استفاده شده است.

library(caret)
library(class)
library(skimr)
library(corrplot)
library(DataExplorer)
library(SmartEDA)
library(summarytools)

نقش ابزارهای منتخب:

هسته اصلی پردازش و مدل‌سازی در این پروژه بر عهده پکیج قدرتمند caret است که فرآیندهای آموزش و ارزیابی را یکپارچه می‌سازد. برای تحلیل‌های آماری اولیه و درک سریع ساختار داده‌ها از skimr و DataExplorer بهره برده‌ایم. همچنین جهت بررسی همبستگی متغیرها که در حذف ویژگی‌های زائد حیاتی است، از corrplot استفاده شده است.

2.2 فراخوانی مجموعه داده

داده‌های خام به‌صورت مستقیم از مخزن گیت‌هاب پروژه بارگذاری می‌شوند. این روش دسترسی، تکرارپذیری کد را برای سایر پژوهشگران تضمین می‌کند.

data <- read.csv("https://raw.githubusercontent.com/sainsdataid/dataset/main/wine-quality-binary.csv")

بررسی اولیه ساختار داده:

پس از بارگذاری، ضروری است تا با استفاده از توابع skim و str، نگاهی اجمالی به ابعاد، نوع متغیرها و سلامت کلی داده‌ها داشته باشیم. این گام به ما کمک می‌کند تا استراتژی مناسبی برای پیش‌پردازش اتخاذ کنیم.

skim(data)
Data summary
Name data
Number of rows 1143
Number of columns 13
_______________________
Column type frequency:
character 1
numeric 12
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
quality 0 1 3 4 0 2 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
id 0 1 572.00 330.10 1.00 286.50 572.00 857.50 1143.00 ▇▇▇▇▇
fixed.acidity 0 1 8.31 1.75 4.60 7.10 7.90 9.10 15.90 ▂▇▂▁▁
volatile.acidity 0 1 0.53 0.18 0.12 0.39 0.52 0.64 1.58 ▅▇▂▁▁
citric.acid 0 1 0.27 0.20 0.00 0.09 0.25 0.42 1.00 ▇▆▅▁▁
residual.sugar 0 1 2.53 1.36 0.90 1.90 2.20 2.60 15.50 ▇▁▁▁▁
chlorides 0 1 0.09 0.05 0.01 0.07 0.08 0.09 0.61 ▇▁▁▁▁
free.sulfur.dioxide 0 1 15.62 10.25 1.00 7.00 13.00 21.00 68.00 ▇▅▂▁▁
total.sulfur.dioxide 0 1 45.91 32.78 6.00 21.00 37.00 61.00 289.00 ▇▂▁▁▁
density 0 1 1.00 0.00 0.99 1.00 1.00 1.00 1.00 ▁▃▇▂▁
pH 0 1 3.31 0.16 2.74 3.20 3.31 3.40 4.01 ▁▅▇▂▁
sulphates 0 1 0.66 0.17 0.33 0.55 0.62 0.73 2.00 ▇▅▁▁▁
alcohol 0 1 10.44 1.08 8.40 9.50 10.20 11.10 14.90 ▇▇▃▁▁
str(data)
## 'data.frame':    1143 obs. of  13 variables:
##  $ id                  : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ fixed.acidity       : num  7.4 7.8 7.8 11.2 7.4 7.4 7.9 7.3 7.8 6.7 ...
##  $ volatile.acidity    : num  0.7 0.88 0.76 0.28 0.7 0.66 0.6 0.65 0.58 0.58 ...
##  $ citric.acid         : num  0 0 0.04 0.56 0 0 0.06 0 0.02 0.08 ...
##  $ residual.sugar      : num  1.9 2.6 2.3 1.9 1.9 1.8 1.6 1.2 2 1.8 ...
##  $ chlorides           : num  0.076 0.098 0.092 0.075 0.076 0.075 0.069 0.065 0.073 0.097 ...
##  $ free.sulfur.dioxide : num  11 25 15 17 11 13 15 15 9 15 ...
##  $ total.sulfur.dioxide: num  34 67 54 60 34 40 59 21 18 65 ...
##  $ density             : num  0.998 0.997 0.997 0.998 0.998 ...
##  $ pH                  : num  3.51 3.2 3.26 3.16 3.51 3.51 3.3 3.39 3.36 3.28 ...
##  $ sulphates           : num  0.56 0.68 0.65 0.58 0.56 0.56 0.46 0.47 0.57 0.54 ...
##  $ alcohol             : num  9.4 9.8 9.8 9.8 9.4 9.4 9.4 10 9.5 9.2 ...
##  $ quality             : chr  "LOW" "LOW" "LOW" "HIGH" ...

3 پیش‌پردازش و آماده‌سازی داده‌ها

3.1 پالایش ویژگی‌ها

در این مرحله، ستون id که صرفاً شناسه‌ای برای ردیف‌هاست و فاقد ارزش اطلاعاتی برای مدل‌سازی است، حذف می‌گردد. همچنین، متغیر هدف (quality) که ماهیت طبقه‌ای دارد، به ساختار Factor تبدیل می‌شود تا برای الگوریتم‌های طبقه‌بندی قابل فهم باشد.

data$id <- NULL
data$quality <- factor(data$quality)

3.2 بررسی توازن کلاس‌ها

یکی از چالش‌های رایج در یادگیری ماشین، عدم توازن داده‌هاست. در اینجا توزیع فراوانی متغیر هدف را بررسی می‌کنیم تا مطمئن شویم مدل دچار اریبی به سمت کلاس غالب نخواهد شد.

quality <- data.frame(table(data$quality))
quality$Prop <- round(quality$Freq/sum(quality$Freq), 3)
print(quality)
##   Var1 Freq  Prop
## 1 HIGH  621 0.543
## 2  LOW  522 0.457

تحلیل توزیع کلاس‌ها:

بررسی جدول فوق نشان می‌دهد که داده‌ها از نظر توزیع کلاس‌ها نسبتاً متعادل (Balanced) هستند (حدود ۵۴٪ در برابر ۴۶٪). این خبر خوبی است، زیرا نیاز به تکنیک‌های پیچیده نمونه‌برداری (مانند SMOTE) را مرتفع می‌سازد و می‌توانیم با اطمینان بیشتری به سراغ مدل‌سازی برویم.

4 تحلیل اکتشافی داده‌ها

پیش از هرگونه مدل‌سازی، باید درک عمیقی از رفتار متغیرها داشته باشیم. نمودارها و آماره‌های زیر به ما در شناسایی داده‌های پرت و الگوی توزیع ویژگی‌ها کمک می‌کنند.

plot_intro(data)

ExpNumStat(data,
by = "GA",
gp = "quality",
Outlier = TRUE,
round = 2)
st_options(plain.ascii = FALSE, style = "rmarkdown")
print(dfSummary(data, graph.magnif = 0.75), method = "pander")
## ### Data Frame Summary  
## #### data  
## **Dimensions:** 1143 x 12  
## **Duplicates:** 125  
## 
## -------------------------------------------------------------------------------------------------------------------------
## No   Variable                Stats / Values             Freqs (% of Valid)    Graph                  Valid      Missing  
## ---- ----------------------- -------------------------- --------------------- ---------------------- ---------- ---------
## 1    fixed.acidity\          Mean (sd) : 8.3 (1.7)\     91 distinct values    \ \ \ \ :\             1143\      0\       
##      [numeric]               min < med < max:\                                \ \ \ \ : .\           (100.0%)   (0.0%)   
##                              4.6 < 7.9 < 15.9\                                \ \ \ \ : :\                               
##                              IQR (CV) : 2 (0.2)                               \ \ : : : .\                               
##                                                                               . : : : : : . .                            
## 
## 2    volatile.acidity\       Mean (sd) : 0.5 (0.2)\     135 distinct values   \ \ \ \ . :\           1143\      0\       
##      [numeric]               min < med < max:\                                \ \ : : :\             (100.0%)   (0.0%)   
##                              0.1 < 0.5 < 1.6\                                 \ \ : : :\                                 
##                              IQR (CV) : 0.2 (0.3)                             \ \ : : : .\                               
##                                                                               . : : : : .                                
## 
## 3    citric.acid\            Mean (sd) : 0.3 (0.2)\     77 distinct values    :\                     1143\      0\       
##      [numeric]               min < med < max:\                                : \ \ .\               (100.0%)   (0.0%)   
##                              0 < 0.2 < 1\                                     : \ \ : . .\                               
##                              IQR (CV) : 0.3 (0.7)                             : : : : : .\                               
##                                                                               : : : : : : .                              
## 
## 4    residual.sugar\         Mean (sd) : 2.5 (1.4)\     80 distinct values    :\                     1143\      0\       
##      [numeric]               min < med < max:\                                :\                     (100.0%)   (0.0%)   
##                              0.9 < 2.2 < 15.5\                                : .\                                       
##                              IQR (CV) : 0.7 (0.5)                             : :\                                       
##                                                                               : : . .                                    
## 
## 5    chlorides\              Mean (sd) : 0.1 (0)\       131 distinct values   \ \ :\                 1143\      0\       
##      [numeric]               min < med < max:\                                \ \ :\                 (100.0%)   (0.0%)   
##                              0 < 0.1 < 0.6\                                   \ \ :\                                     
##                              IQR (CV) : 0 (0.5)                               : :\                                       
##                                                                               : :                                        
## 
## 6    free.sulfur.dioxide\    Mean (sd) : 15.6 (10.3)\   53 distinct values    . :\                   1143\      0\       
##      [numeric]               min < med < max:\                                : : :\                 (100.0%)   (0.0%)   
##                              1 < 13 < 68\                                     : : :\                                     
##                              IQR (CV) : 14 (0.7)                              : : : : .\                                 
##                                                                               : : : : : .                                
## 
## 7    total.sulfur.dioxide\   Mean (sd) : 45.9 (32.8)\   138 distinct values   :\                     1143\      0\       
##      [numeric]               min < med < max:\                                :\                     (100.0%)   (0.0%)   
##                              6 < 37 < 289\                                    : :\                                       
##                              IQR (CV) : 40 (0.7)                              : : .\                                     
##                                                                               : : : . .                                  
## 
## 8    density\                Mean (sd) : 1 (0)\         388 distinct values   \ \ \ \ \ \ \ \ : .\   1143\      0\       
##      [numeric]               min < med < max:\                                \ \ \ \ \ \ \ \ : :\   (100.0%)   (0.0%)   
##                              1 < 1 < 1\                                       \ \ \ \ \ \ : : :\                         
##                              IQR (CV) : 0 (0)                                 \ \ \ \ \ \ : : : :\                       
##                                                                               \ \ . : : : : : .                          
## 
## 9    pH\                     Mean (sd) : 3.3 (0.2)\     87 distinct values    \ \ \ \ \ \ \ \ :\     1143\      0\       
##      [numeric]               min < med < max:\                                \ \ \ \ \ \ . :\       (100.0%)   (0.0%)   
##                              2.7 < 3.3 < 4\                                   \ \ \ \ \ \ : : :\                         
##                              IQR (CV) : 0.2 (0)                               \ \ \ \ \ \ : : : .\                       
##                                                                               \ \ . : : : : :                            
## 
## 10   sulphates\              Mean (sd) : 0.7 (0.2)\     89 distinct values    \ \ :\                 1143\      0\       
##      [numeric]               min < med < max:\                                \ \ :\                 (100.0%)   (0.0%)   
##                              0.3 < 0.6 < 2\                                   \ \ : .\                                   
##                              IQR (CV) : 0.2 (0.3)                             \ \ : :\                                   
##                                                                               : : : .                                    
## 
## 11   alcohol\                Mean (sd) : 10.4 (1.1)\    61 distinct values    \ \ :\                 1143\      0\       
##      [numeric]               min < med < max:\                                \ \ :\                 (100.0%)   (0.0%)   
##                              8.4 < 10.2 < 14.9\                               \ \ : : :\                                 
##                              IQR (CV) : 1.6 (0.1)                             \ \ : : : . .\                             
##                                                                               . : : : : : :                              
## 
## 12   quality\                1\. HIGH\                  621 (54.3%)\          IIIIIIIIII \           1143\      0\       
##      [factor]                2\. LOW                    522 (45.7%)           IIIIIIIII              (100.0%)   (0.0%)   
## -------------------------------------------------------------------------------------------------------------------------

نکات کلیدی حاصل از EDA:

  • گزارش plot_intro فقدان داده‌های گم‌شده (Missing Values) را تأیید می‌کند که فرآیند پاکسازی را تسهیل می‌نماید.
  • خروجی ExpNumStat وجود داده‌های پرت در برخی ویژگی‌های شیمیایی را نشان می‌دهد، اما با توجه به ماهیت داده‌های آزمایشگاهی، این مقادیر می‌توانند واقعی باشند و نه خطا.
  • بررسی داده‌های تکراری نشان داد که حذف آن‌ها باعث کاهش دقت مدل به زیر ۷۰٪ می‌شود؛ بنابراین تصمیم بر حفظ تمامی مشاهدات گرفته شد.

5 مدل‌سازی با الگوریتم K-Nearest Neighbors

5.1 تقسیم‌بندی داده‌ها

برای سنجش واقعی عملکرد مدل، داده‌ها را با نسبت ۷۰ به ۳۰ افراز می‌کنیم. استفاده از روش نمونه‌گیری طبقه‌ای (Stratified Sampling) تضمین می‌کند که نسبت کیفیت خوب به بد در هر دو بخش آموزش و آزمون یکسان باقی بماند.

set.seed(251222)

trainindex <- createDataPartition(data$quality, p = 0.7, list = FALSE, times = 1)

data.train <- data[trainindex, ]
data.test <- data[-trainindex, ]

cbind("train" = table(data.train$quality), "test" = table(data.test$quality))
##      train test
## HIGH   435  186
## LOW    366  156

5.2 اعتبارسنجی ساختار داده‌ها

پس از تقسیم داده‌ها، باید مطمئن شویم که روابط آماری میان متغیرها مخدوش نشده است. ماتریس‌های همبستگی زیر این موضوع را بررسی می‌کنند.

par(mfrow=c(1, 3))

corrplot(cor(Filter(is.numeric, data)),
method = "color",
title = "Original Data",
mar=c(0,0,2,0))

corrplot(cor(Filter(is.numeric, data.train)),
method = "color",
title = "Train Data",
mar=c(0,0,2,0))

corrplot(cor(Filter(is.numeric, data.test)),
method = "color",
title = "Test Data",
mar=c(0,0,2,0))

par(mfrow=c(1, 1))

تفسیر همبستگی‌ها:

شباهت بصری بسیار زیاد بین سه نمودار فوق، یک نشانه عالی است. این امر تأیید می‌کند که داده‌های آموزشی ما نماینده‌ای صادق از کل جامعه آماری هستند و روابط بین متغیرها (مثلاً رابطه مثبت بین چگالی و اسیدیته ثابت) در فرآیند افراز داده حفظ شده است.

5.3 استانداردسازی

الگوریتم KNN بر پایه محاسبه فاصله (اقلیدسی) عمل می‌کند. متغیرهایی با مقادیر عددی بزرگ می‌توانند بر متغیرهای کوچک سایه بیندازند. برای رفع این مشکل، تمام متغیرهای عددی را به بازه [0, 1] نرمال‌سازی می‌کنیم.

preproc.params <- preProcess(data.train[, -12], method = "range")
scaled.data.train <- predict(preproc.params, data.train[, -12])
scaled.data.test <- predict(preproc.params, data.test[, -12])

summary(scaled.data.train)
##  fixed.acidity    volatile.acidity  citric.acid     residual.sugar   
##  Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.00000  
##  1st Qu.:0.2273   1st Qu.:0.1918   1st Qu.:0.0900   1st Qu.:0.06897  
##  Median :0.3000   Median :0.2740   Median :0.2400   Median :0.08966  
##  Mean   :0.3344   Mean   :0.2819   Mean   :0.2641   Mean   :0.11321  
##  3rd Qu.:0.4091   3rd Qu.:0.3562   3rd Qu.:0.4200   3rd Qu.:0.11724  
##  Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.00000  
##    chlorides       free.sulfur.dioxide total.sulfur.dioxide    density      
##  Min.   :0.00000   Min.   :0.00000     Min.   :0.00000      Min.   :0.0000  
##  1st Qu.:0.09683   1st Qu.:0.08955     1st Qu.:0.05515      1st Qu.:0.4031  
##  Median :0.11185   Median :0.17910     Median :0.11029      Median :0.4824  
##  Mean   :0.12606   Mean   :0.21555     Mean   :0.14243      Mean   :0.4894  
##  3rd Qu.:0.13189   3rd Qu.:0.29851     3rd Qu.:0.19853      3rd Qu.:0.5712  
##  Max.   :1.00000   Max.   :1.00000     Max.   :1.00000      Max.   :1.0000  
##        pH           sulphates         alcohol      
##  Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
##  1st Qu.:0.3622   1st Qu.:0.1317   1st Qu.:0.1964  
##  Median :0.4488   Median :0.1737   Median :0.3214  
##  Mean   :0.4514   Mean   :0.1943   Mean   :0.3640  
##  3rd Qu.:0.5276   3rd Qu.:0.2335   3rd Qu.:0.4821  
##  Max.   :1.0000   Max.   :1.0000   Max.   :1.0000

5.4 آموزش مدل و تنظیم ابرپارامترها

برای یافتن بهترین تعداد همسایه (k)، از روش اعتبارسنجی متقابل ۱۰ لایه استفاده شده است. ما مقادیر مختلف k (از ۱ تا ۳۵) را آزمایش می‌کنیم.

ctrl <- trainControl(method = "cv",
number = 10,
classProbs = TRUE,
summaryFunction = twoClassSummary)

grid <- expand.grid(k = seq(1, 35, by = 1))

set.seed(123)
knn_fit <- train(quality ~ .,
data = data.train,
method = "knn",
trControl = ctrl,
tuneGrid = grid,
metric = "ROC")

print(knn_fit)
## k-Nearest Neighbors 
## 
## 801 samples
##  11 predictor
##   2 classes: 'HIGH', 'LOW' 
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold) 
## Summary of sample sizes: 720, 721, 721, 722, 721, 721, ... 
## Resampling results across tuning parameters:
## 
##   k   ROC        Sens       Spec     
##    1  0.6395686  0.6369450  0.6421922
##    2  0.6534987  0.6346723  0.5930180
##    3  0.6644854  0.6737844  0.5846096
##    4  0.6691036  0.6460359  0.6252252
##    5  0.6735242  0.6575581  0.6040541
##    6  0.6742145  0.6713531  0.5873123
##    7  0.6704632  0.6714588  0.5681682
##    8  0.6785554  0.6643235  0.5874625
##    9  0.6860569  0.6804440  0.6092342
##   10  0.6880843  0.7009514  0.6064565
##   11  0.6990067  0.6894292  0.6093093
##   12  0.7049096  0.6941332  0.6095345
##   13  0.7024106  0.7008985  0.6202703
##   14  0.7020320  0.7030127  0.6148649
##   15  0.7046046  0.6986258  0.6254505
##   16  0.7037783  0.6987315  0.6144895
##   17  0.7016306  0.6894292  0.6090841
##   18  0.7027243  0.6939218  0.6090841
##   19  0.6989746  0.6893763  0.5955706
##   20  0.7005414  0.7056025  0.6010511
##   21  0.6999189  0.7056025  0.5874625
##   22  0.6997701  0.7080867  0.5821321
##   23  0.7053252  0.7217230  0.5957207
##   24  0.7033227  0.7217230  0.6037538
##   25  0.7042287  0.7171776  0.5958709
##   26  0.7065551  0.7193446  0.5846847
##   27  0.7034810  0.7146406  0.5929429
##   28  0.7052123  0.7216702  0.5792042
##   29  0.7061664  0.7215645  0.5765015
##   30  0.7037258  0.7216702  0.5681682
##   31  0.7022616  0.7284884  0.5601351
##   32  0.7035852  0.7308140  0.5710961
##   33  0.7008683  0.7353594  0.5629129
##   34  0.7025120  0.7422833  0.5737988
##   35  0.7058676  0.7468816  0.5602102
## 
## ROC was used to select the optimal model using the largest value.
## The final value used for the model was k = 26.
plot(knn_fit)

بهینه‌سازی پارامتر K:

نمودار فوق روند تغییرات عملکرد مدل را نشان می‌دهد. مشاهده می‌شود که با افزایش k، ابتدا دقت بهبود می‌یابد و سپس به ثبات می‌رسد. الگوریتم بر اساس معیار ROC، مقدار بهینه را پیشنهاد داده است. این انتخاب تعادل مناسبی بین واریانس و بایاس برقرار می‌کند.

6 ارزیابی نهایی مدل

اکنون مدل نهایی را با k بهینه روی داده‌های آزمون اجرا می‌کنیم تا عملکرد واقعی آن مشخص شود.

pred.knn <- knn(train=scaled.data.train, test=scaled.data.test,
cl=data.train$quality, k=31)

print(pred.knn)
##   [1] LOW  LOW  LOW  HIGH LOW  LOW  HIGH HIGH HIGH LOW  LOW  LOW  LOW  LOW  HIGH
##  [16] LOW  LOW  LOW  LOW  LOW  HIGH LOW  LOW  LOW  LOW  LOW  HIGH LOW  HIGH LOW 
##  [31] LOW  LOW  LOW  HIGH LOW  LOW  LOW  LOW  LOW  LOW  LOW  LOW  LOW  HIGH LOW 
##  [46] LOW  HIGH LOW  LOW  LOW  LOW  LOW  HIGH LOW  HIGH HIGH LOW  HIGH HIGH LOW 
##  [61] HIGH HIGH HIGH HIGH HIGH HIGH LOW  HIGH LOW  LOW  LOW  HIGH LOW  HIGH HIGH
##  [76] HIGH LOW  HIGH HIGH HIGH HIGH HIGH HIGH HIGH HIGH LOW  HIGH HIGH HIGH HIGH
##  [91] HIGH HIGH HIGH LOW  LOW  LOW  HIGH LOW  HIGH LOW  LOW  HIGH LOW  HIGH HIGH
## [106] HIGH HIGH HIGH HIGH HIGH HIGH HIGH HIGH HIGH HIGH LOW  HIGH HIGH HIGH HIGH
## [121] HIGH LOW  HIGH HIGH HIGH HIGH HIGH HIGH HIGH LOW  HIGH LOW  HIGH LOW  LOW 
## [136] LOW  LOW  HIGH HIGH HIGH LOW  LOW  LOW  HIGH LOW  HIGH HIGH HIGH LOW  HIGH
## [151] LOW  LOW  LOW  LOW  HIGH LOW  LOW  LOW  HIGH HIGH LOW  LOW  LOW  HIGH HIGH
## [166] LOW  LOW  LOW  HIGH LOW  HIGH HIGH HIGH LOW  LOW  LOW  LOW  LOW  HIGH LOW 
## [181] HIGH LOW  LOW  HIGH LOW  LOW  HIGH HIGH HIGH HIGH LOW  HIGH HIGH HIGH HIGH
## [196] LOW  LOW  HIGH HIGH HIGH LOW  LOW  HIGH HIGH HIGH HIGH HIGH HIGH HIGH LOW 
## [211] HIGH HIGH HIGH HIGH LOW  HIGH HIGH LOW  HIGH HIGH LOW  HIGH HIGH HIGH HIGH
## [226] HIGH HIGH HIGH HIGH HIGH HIGH HIGH HIGH LOW  HIGH HIGH HIGH HIGH HIGH HIGH
## [241] HIGH HIGH LOW  HIGH HIGH HIGH HIGH HIGH LOW  HIGH HIGH LOW  LOW  LOW  LOW 
## [256] HIGH HIGH HIGH LOW  LOW  HIGH LOW  HIGH HIGH LOW  LOW  HIGH HIGH HIGH HIGH
## [271] LOW  LOW  LOW  HIGH LOW  HIGH HIGH HIGH HIGH LOW  LOW  LOW  HIGH LOW  LOW 
## [286] LOW  HIGH HIGH HIGH LOW  HIGH LOW  LOW  HIGH LOW  HIGH LOW  LOW  HIGH LOW 
## [301] HIGH HIGH LOW  HIGH LOW  HIGH LOW  HIGH HIGH HIGH HIGH HIGH HIGH HIGH LOW 
## [316] HIGH LOW  HIGH HIGH HIGH HIGH LOW  HIGH LOW  HIGH LOW  HIGH HIGH HIGH LOW 
## [331] LOW  HIGH LOW  LOW  HIGH HIGH LOW  HIGH HIGH HIGH HIGH HIGH
## Levels: HIGH LOW
conf_matrix <- confusionMatrix(pred.knn, data.test$quality)
print(conf_matrix)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction HIGH LOW
##       HIGH  145  51
##       LOW    41 105
##                                           
##                Accuracy : 0.731           
##                  95% CI : (0.6807, 0.7773)
##     No Information Rate : 0.5439          
##     P-Value [Acc > NIR] : 8.407e-13       
##                                           
##                   Kappa : 0.455           
##                                           
##  Mcnemar's Test P-Value : 0.3481          
##                                           
##             Sensitivity : 0.7796          
##             Specificity : 0.6731          
##          Pos Pred Value : 0.7398          
##          Neg Pred Value : 0.7192          
##              Prevalence : 0.5439          
##          Detection Rate : 0.4240          
##    Detection Prevalence : 0.5731          
##       Balanced Accuracy : 0.7263          
##                                           
##        'Positive' Class : HIGH            
## 

6.1 تحلیل جامع عملکرد

results <- knn_fit$results
plot(x = results$k,
y = results$ROC,
type = "b",
pch = 19,
col = "blue",
main = "Model Performance vs K Value",
xlab = "Number of Neighbors (k)",
ylab = "ROC (AUC)")

abline(v = knn_fit$bestTune$k, col = "red", lty = 2)

actual_values <- factor(data.test$quality, levels = levels(pred.knn))

final_results <- confusionMatrix(pred.knn, actual_values, mode = "prec_recall")

print(final_results)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction HIGH LOW
##       HIGH  145  51
##       LOW    41 105
##                                           
##                Accuracy : 0.731           
##                  95% CI : (0.6807, 0.7773)
##     No Information Rate : 0.5439          
##     P-Value [Acc > NIR] : 8.407e-13       
##                                           
##                   Kappa : 0.455           
##                                           
##  Mcnemar's Test P-Value : 0.3481          
##                                           
##               Precision : 0.7398          
##                  Recall : 0.7796          
##                      F1 : 0.7592          
##              Prevalence : 0.5439          
##          Detection Rate : 0.4240          
##    Detection Prevalence : 0.5731          
##       Balanced Accuracy : 0.7263          
##                                           
##        'Positive' Class : HIGH            
## 

نتیجه‌گیری نهایی و تفسیر دستاوردها:

تحلیل خروجی‌های مدل KNN نتایج قابل توجهی را آشکار می‌سازد:

  1. دقت کلی (Accuracy): مدل توانست به دقت بالایی دست یابد. با در نظر گرفتن پیچیدگی شیمیایی داده‌ها و استفاده از یک الگوریتم پایه، این نتیجه بسیار مطلوب است.

  2. تعادل دقت و بازیابی:

    • حساسیت (Sensitivity): مدل در شناسایی شراب‌های با کیفیت بالا عملکرد خوبی دارد.
    • ویژگی (Specificity): مدل در تشخیص شراب‌های بی‌کیفیت نیز عملکرد قابل قبولی دارد.
  3. انتخاب هوشمندانه K: انتخاب مقدار بهینه برای همسایگان باعث شده مدل از جزئیات نویزگونه عبور کرده و الگوهای کلی‌تر و پایدارتر را یاد بگیرد.


پیشنهاد برای تحقیقات آتی:

برای کاربردهای صنعتی پیشنهاد می‌شود از الگوریتم‌های درختی مانند Random Forest یا XGBoost استفاده شود. این الگوریتم‌ها می‌توانند تعاملات غیرخطی پیچیده بین ترکیبات شیمیایی را بهتر مدل‌سازی کنند و احتمالاً دقت را بهبود بخشند.